// Copyright (c) [Year] [name of copyright holder]
// [Software Name] is licensed under Mulan PSL v2.
// You can use this software according to the terms and conditions of the Mulan PSL v2. 
// You may obtain a copy of Mulan PSL v2 at:
//          http://license.coscl.org.cn/MulanPSL2 
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.  
// See the Mulan PSL v2 for more details.

/*!
 * \autor captainpeng
 * \date 2019-9-30
 * \version 1.0
 * \copyright
 */

#ifndef MY_UNICODE_HPP
#define MY_UNICODE_HPP

#define UNICODEBIT 32

#include<string>
#include"mystd.hpp"

namespace my{

    using unicode_t = typename cint<UNICODEBIT>::intType;

    namespace unicode{
        static constexpr unicode_t empty = 0;
        static constexpr unicode_t eof = -1;
        static constexpr unicode_t error = -2;
        static constexpr unicode_t lack = -3;
        static constexpr unicode_t replace = 0x5928; // 夨

        static constexpr unicode_t Space = 0x32; // 半角空格
        static constexpr unicode_t HalfAngleBegin = 0x21; // !
        static constexpr unicode_t HalfAngleEnd = 0x7e; // ~

        static constexpr unicode_t AngleOffset = 0xfee0; // 65248

        static constexpr unicode_t FullSpace = 0x3000; // 全角空格
        static constexpr unicode_t FullAngleBegin = 0xff01; // ！
        static constexpr unicode_t FullAngleEnd = 0xff5e; // ～

        static constexpr unicode_t _0 = (unicode_t)'0';
        static constexpr unicode_t _1 = (unicode_t)'1';
        static constexpr unicode_t _2 = (unicode_t)'2';
        static constexpr unicode_t _3 = (unicode_t)'3';
        static constexpr unicode_t _4 = (unicode_t)'4';
        static constexpr unicode_t _5 = (unicode_t)'5';
        static constexpr unicode_t _6 = (unicode_t)'6';
        static constexpr unicode_t _7 = (unicode_t)'7';
        static constexpr unicode_t _8 = (unicode_t)'8';
        static constexpr unicode_t _9 = (unicode_t)'9';

        static constexpr unicode_t _a = (unicode_t)'a';
        static constexpr unicode_t _b = (unicode_t)'b';
        static constexpr unicode_t _c = (unicode_t)'c';
        static constexpr unicode_t _d = (unicode_t)'d';
        static constexpr unicode_t _e = (unicode_t)'e';
        static constexpr unicode_t _f = (unicode_t)'f';
        static constexpr unicode_t _g = (unicode_t)'g';
        static constexpr unicode_t _h = (unicode_t)'h';
        static constexpr unicode_t _i = (unicode_t)'i';
        static constexpr unicode_t _j = (unicode_t)'j';
        static constexpr unicode_t _k = (unicode_t)'k';
        static constexpr unicode_t _l = (unicode_t)'l';
        static constexpr unicode_t _m = (unicode_t)'m';
        static constexpr unicode_t _n = (unicode_t)'n';
        static constexpr unicode_t _o = (unicode_t)'o';
        static constexpr unicode_t _p = (unicode_t)'p';
        static constexpr unicode_t _q = (unicode_t)'q';
        static constexpr unicode_t _r = (unicode_t)'r';
        static constexpr unicode_t _s = (unicode_t)'s';
        static constexpr unicode_t _t = (unicode_t)'t';
        static constexpr unicode_t _u = (unicode_t)'u';
        static constexpr unicode_t _v = (unicode_t)'v';
        static constexpr unicode_t _w = (unicode_t)'w';
        static constexpr unicode_t _x = (unicode_t)'x';
        static constexpr unicode_t _y = (unicode_t)'y';
        static constexpr unicode_t _z = (unicode_t)'z';

        static constexpr unicode_t _A = (unicode_t)'A';
        static constexpr unicode_t _B = (unicode_t)'B';
        static constexpr unicode_t _C = (unicode_t)'C';
        static constexpr unicode_t _D = (unicode_t)'D';
        static constexpr unicode_t _E = (unicode_t)'E';
        static constexpr unicode_t _F = (unicode_t)'F';
        static constexpr unicode_t _G = (unicode_t)'G';
        static constexpr unicode_t _H = (unicode_t)'H';
        static constexpr unicode_t _I = (unicode_t)'I';
        static constexpr unicode_t _J = (unicode_t)'J';
        static constexpr unicode_t _K = (unicode_t)'K';
        static constexpr unicode_t _L = (unicode_t)'L';
        static constexpr unicode_t _M = (unicode_t)'M';
        static constexpr unicode_t _N = (unicode_t)'N';
        static constexpr unicode_t _O = (unicode_t)'O';
        static constexpr unicode_t _P = (unicode_t)'P';
        static constexpr unicode_t _Q = (unicode_t)'Q';
        static constexpr unicode_t _R = (unicode_t)'R';
        static constexpr unicode_t _S = (unicode_t)'S';
        static constexpr unicode_t _T = (unicode_t)'T';
        static constexpr unicode_t _U = (unicode_t)'U';
        static constexpr unicode_t _V = (unicode_t)'V';
        static constexpr unicode_t _W = (unicode_t)'W';
        static constexpr unicode_t _X = (unicode_t)'X';
        static constexpr unicode_t _Y = (unicode_t)'Y';
        static constexpr unicode_t _Z = (unicode_t)'Z';

        static inline unicode_t ToHalf(const unicode_t u){
            if(u == FullSpace)
                return Space;
            else if(u >= FullAngleBegin && u <= FullAngleEnd)
                return u - AngleOffset;
            
            return u;
        }

        static inline unicode_t ToFull(const unicode_t u){
            if(u == Space)
                return FullSpace;
            else if(u >= HalfAngleBegin && u <= HalfAngleEnd)
                return u + AngleOffset;

            return u;
        }

        static inline wchar_t ToWChar(const unicode_t u){
            return (wchar_t) u;
        }
    }

    template<>
    class charLib<unicode_t>{
        charLib() = delete;
    public:
        using charType = unicode_t;
        using charPtr = unicode_t *;
        using intType = unicode_t;

        static inline size_t strlen(const unicode_t * src){
            size_t sum = 0;
            while(src[sum] != unicode::empty)
                ++sum;
            return sum;
        }

    };
        
    template<int NUM>
    class utf;
}

#endif
